.TH LIBPFM 3  "July , 2003" "" "Linux Programmer's Manual"
.SH NAME
pfm_dispatch_events \- determine PMC registers values for a set of events to measure
.SH SYNOPSIS
.nf
.B #include <perfmon/pfmlib.h>
.sp
.BI "int pfm_dispatch_events(pfmlib_input_param_t *"p ", void *" mod_in ", pfmlib_output_param_t *" q, "void *" mod_out ");"
.sp
.SH DESCRIPTION
This function is the central piece of the library. It is important to understand
that the library does not effectively program the PMU, i.e., it does not make
the operating system calls. The PMU is never actually accessed by the 
library. Instead, the library helps applications prepare the arguments to pass to
the kernel. In particular, it sets up the values to program into the PMU
configuration registers (PMC). The list of used data registers (PMD) is also
returned.
.sp
The input argument are divided into two categories: the generic arguments in \fBp\fR
and the optional PMU model specific arguments in \fBmod_in\fR.
The same applies for the output arguments: \fBq\fR contains the generic
output arguments and \fBmod_out\fR the optional PMU model specific arguments.
.sp
An application describes what it wants to measure in the \fBin\fR and if it uses some model
specific features, such as opcode matching on Itanium 2 processors, it must pass a pointer to the 
relevant model-specific input parameters in \fBmod_in\fR. The generic output parameters
contains the register index and values for the PMC and PMD registers needed to
make the measurement. The index mapping is guaranteed to match the mapping used
by the Linux perfmon2 interface. In case the library is not used on this system,
the hardware register addresses or indexes can also be retrieved from the output
structure.
.sp
The \fBpfmlib_input_param_t\fR structure is defined as follows:
.sp
.nf
typedef struct 
	int           event;
	unsigned int  plm;
	unsigned long flags;
	unsigned int  unit_masks[PFMLIB_MAX_MASKS_PER_EVENT];
	unsigned int  num_masks;
} pfmlib_event_t;

typedef struct {
	unsigned int     pfp_event_count;
	unsigned int     pfp_dfl_plm;
	unsigned int     pfp_flags;
	pfmlib_event_t   pfp_events[PFMLIB_MAX_PMCS];
	pfmlib_regmask_t pfp_unavail_pmcs;
} pfmlib_input_param_t;
.fi
.sp
The structure mostly contains one table, called \fBpfp_events\fR which describes
the events to be measured. The number of submitted events is indicated by 
\fBpfp_event_count\fR.

Each event is described in the \fBpfp_events\fR table by an opaque descriptor stored in
the \fBevent\fR field. This descriptor is obtained with the \fBpfm_find_full_event()\fR
or derivative functions.  For some events, it may be necessary to specify at least one
unit mask in the \fBunit_masks\fR table. A unit mask is yet another opaque descriptor
obtained via the \fBpfm_find_event_mask()\fR or \fBpfm_find_full_event()\fR functions. Typically, if
an event supports multiple unit masks, they can be combined in which case more than one
entry in \fBunit_masks\fR must be specified. The actual number of unit mask descriptors
passed must be indicated in \fBnum_masks\fR. When no unit mask is used, this
field must be set to 0.

A privilege level mask for the event can be provided in \fBplm\fR.  This is a bitmask where
each bit indicates a privilege level at which to monitor, more than one bit can be set.
The library supports up to four levels, but depending on the PMU model, some levels may not be
available. The levels are as follows:
.TP
.B PFM_PLM0
monitor at the privilege level 0. For many architectures, this means kernel level
.TP 
.B PFM_PLM1
monitor at privilege level 1
.TP 
.B PFM_PLM2
monitor at privilege level 2
.TP 
.B PFM_PLM3
monitor at the privilege level 3. For many architectures, this means user level
.LP
.sp
.sp
Events with a \fBplm\fR value of 0 will use the default privilege level mask
as indicated by \fBpfp_dfl_plm\fR which must be set to any combinations of
values described above. It is illegal to have a value of 0 for this field.
.sp
The \fBpfp_flags\fR field contains a set of flags that affect the whole
set of events to be monitored. The currently defined flags are:
.TP
.B PFMLIB_PFP_SYSTEMWIDE
indicates that the monitors are to be used in a system-wide monitoring session.
This could influence the way the library sets up some register values.
.sp
.LP
The \fBpfp_unavail_pmcs\fR bitmask can be used by applications to communicate
to the library the list of PMC registers which are not available on the system.
Some kernels may allocate certain PMC registers (and associated data registers)
for other purposes. Those registers must not be used by the library
otherwise the assignment of events to PMC registers may be rejected by the
kernel. Applications must figure out which registers are available using 
a kernel interface at their disposal, the library does not provide this
service. The library expect the restrictions to be expressed using the Linux
perfmon2 PMC register mapping.
.LP
Refer to the PMU specific manual for a description of the model-specific 
input parameters to be passed in \fBmod_in\fR.

The generic output parameters are contained in the fBpfmlib_output_param_t\fR
structure which is defined as:
.sp
.nf
typedef struct {
    unsigned long long reg_value;
    unsigned int       reg_num;
    unsigned long      reg_addr;
} pfmlib_reg_t;

typedef struct {
    unsigned int pfp_pmc_count;
    unsigned int pfp_pmd_count;
    pfmlib_reg_t pfp_pmcs[PFMLIB_MAX_PMCS];
    pfmlib_reg_t pfp_pmds[PFMLIB_MAX_PMDS];
} pfmlib_output_param_t;
.fi
.sp
The number of valid entries  in the \fBpfp_pmcs\fR table is indicated by \fBpfp_pmc_count\fR.
The number of valid entries  in the \fBpfp_pmds\fR table is indicated by \fBpfp_pmd_count\fR.
Each entry in both tables is of type \fBpfmlib_reg_t\fR.
.sp
In the \fBpfp_pmcs\fR table, the \fBreg_num\fR contains the PMC register index (perfmon2 mapping),
and the \fBreg_value\fR contains a 64-bit value to be used to program the PMC register.
The \fBreg_addr\fR indicates the hardware address or index for the PMC register.
.sp
In the \fBpfp_pmds\fR table, the \fBreg_num\fR contains the PMD register index
(perfmon2 mapping). the \fBreg_value\fR is ignored. The \fBreg_addr\fR indicates the hardware
address or index for the PMC register.
.sp
Refer to the PMU specific manual for a description of the model-specific 
output parameters to be returned in \fBmod_out\fR.
.sp
The current implementation of the \fBpfm_dispatch_events()\fR function completely overwrites
the \fBpfmlib_output_param\fR structure. In other words, results do not accumulate
into the \fBpfp_pmcs\fR table across multiple calls. Unused fields are
guaranteed to be zeroed upon successful return.
.sp
Depending on the PMU model, there may not always be a one to one mapping between
a PMC register and a data register. Register dependencies may be more intricate.
However the \fBpfm_dispatch_events()\fR function guarantees certain ordering between the
\fBpfp_pmcs\fR and \fBpfp_pmds\fR tables. In particular, it guarantees that 
the \fBpfp_pmds\fR table always starts with the counters corresponding, in
the same order, to the events as provided in the \fBpfp_event\fR table on input.
There is always one counter per event. Additional PMD registers, if any, come
after.
.SH EXAMPLE
Here is a typical sequence using the perfmon2 interface:
.nf
	#include <perfmon/pfmlib.h>
	...
	pfmlib_input_param_t inp;
	pfmlib_output_param_t outp;
	pfarg_ctx_t ctx;
	pfarg_pmd_t pd[1];
	pfarg_pmc_t pc[1];
	pfarg_load_t load_arg;
	int fd, i;
	int ret;

	if (pfm_initialize() != PFMLIB_SUCCESS) {
		fprintf(stderr, "can't initialize library\\n");
		exit(1);
	}
	memset(&ctx,0, sizeof(ctx));
	memset(&inp,0, sizeof(inp));
	memset(&outp,0, sizeof(outp));
	memset(pd, 0, sizeof(pd));
	memset(pc, 0, sizeof(pc));
	memset(&load_arg, 0, sizeof(load_arg));

	ret = pfm_get_cycle_event(&inp.pfp_events[0]);
	if (ret != PFMLIB_SUCCESS) {
		fprintf(stderr, "cannot find cycle event\\n");
		exit(1);
	}
	inp.pfp_dfl_plm     = PFM_PLM3; 
	inp.pfp_event_count = 1;

	ret = pfm_dispatch_events(&inp, NULL, &outp, NULL);
	if (ret != PFMLIB_SUCCESS) {
		fprintf(stderr, "cannot dispatch events: %s\\n", pfm_strerror(ret));
		exit(1);
	}
	/* propagate pmc value to perfmon2 structures */
	for(i=0; i < outp.pfp_pmc_count; i++) {
		pc[i].reg_num   = outp.pfp_pmcs[i].reg_num;
		pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
	}
	for(i=0; i < outp.pfp_pmd_count; i++) {
		pd[i].reg_num   = outp.pfp_pmds[i].reg_num;
		pd[i].reg_value = 0;
	}
	...
	if (pfm_create_context(&ctx, NULL, 0) == -1 ) {
		...
	}
	fd = ctx.ctx_fd;

	if (pfm_write_pmcs(fd, pc, outp.pfp_pmc_count) == -1) {
		...
	}
	if (pfm_write_pmds(fd, pd, outp.pfp_pmd_count) == -1) {
		...
	}

	load_arg.load_pid = getpid();
	if (pfm_load_context(fd, &load_arg) == -1) {
		...
	}

	pfm_start(fd, NULL);
	/* code to monitor */
	pfm_stop(fd);

	if (pfm_read_pmds(fd, pd, evt.pfp_event_count) == -1) {
		...
	}
	printf("results: %llu\n", pd[0].reg_value);
	...
	close(fd);
	...
.fi

.SH RETURN
The function returns whether or not the call was successful.
A return value of \fBPFMLIB_SUCCESS\fR indicates success, 
otherwise the value is the error code.
.SH ERRORS
.B PFMLIB_ERR_NOINIT
The library has not been initialized properly.
.TP
.B PFMLIB_ERR_INVAL
Some arguments were invalid. For instance the value of *count is zero.
This can also be due to he content of the \fBpfmlib_param_t\fR structure.
.TP
.B PFMLIB_ERR_NOTFOUND
No matching event was found.
.TP
.B PFMLIB_ERR_TOOMANY
The number of events to monitor exceed the number of implemented counters.
.TP
.B PFMLIB_ERR_NOASSIGN
The events cannot be dispatched to the PMC because events have conflicting constraints.
.TP
.B PFMLIB_ERR_MAGIC
The model specific extension does not have the right magic number.
.TP
.B PFMLIB_ERR_FEATCOMB
The set of events and features cannot be combined.
.TP
.B PFMLIB_ERR_EVTMANY
An event has been supplied more than once and is causing resource (PMC) conflicts.
.TP
.B PFMLIB_ERR_IRRINVAL
Invalid code range restriction (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_IRRALIGN
Code range has invalid alignment (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_IRRTOOMANY
Cannot satisfy all the code ranges (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_DRRTOOMANY
Cannot satisfy all the data ranges (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_DRRINVAL
Invalid data range restriction (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_EVTSET
Some events belong to incompatible sets (Itanium 2).
.TP
.B PFMLIB_ERR_EVTINCOMP
Some events cannot be measured at the same time (Itanium 2).
.TP
.B PFMLIB_ERR_IRRTOOBIG
Code range is too big (Itanium 2).
.TP
.B PFMLIB_ERR_UMASK
Invalid or missing unit mask.
.SH SEE ALSO
libpfm_itanium(3), libpfm_itanium2(3), pfm_regmask_set(3), pfm_regmask_clr(3),
pfm_find_event_code_mask(3)
.SH AUTHOR
Stephane Eranian <eranian@hpl.hp.com>
.PP
